﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Text;
using UtilZ.Dotnet.Ex.Json;

namespace UtilZ.Dotnet.Ex.Base
{
    /// <summary>
    /// Object扩展方法类
    /// </summary>
    public static class ObjectEx
    {
        ///// <summary>
        ///// 对象的深拷贝
        ///// </summary>
        ///// <typeparam name="T">目标对象类型</typeparam>
        ///// <param name="obj">原始对象</param>
        ///// <returns>新实例</returns>
        //public static T DeepCopy<T>(object obj)
        //{
        //    using (var memoryStream = new MemoryStream())
        //    {
        //        BinaryFormatter formatter = new BinaryFormatter();
        //        formatter.Serialize(memoryStream, obj);
        //        memoryStream.Position = 0;
        //        T newInstance = (T)formatter.Deserialize(memoryStream);
        //        return newInstance;
        //    }
        //}



        /*
        /// <summary>
        /// 获取变量名称
        /// </summary>
        /// <param name="varPara">变量参数</param>
        /// <param name="exp">变量表达式</param>
        /// <returns>变量名</returns>
        public static string GetVarName(object varPara, System.Linq.Expressions.Expression<Func<object, object>> exp)
        {
            return GetVarName(exp);
        }

        /// <summary>
        /// 获取变量名称
        /// </summary>
        /// <param name="exp">变量表达式</param>
        /// <returns>变量名</returns>
        public static string GetVarName(System.Linq.Expressions.Expression<Func<object, object>> exp)
        {
            string varName = null;
            if (exp.Body is System.Linq.Expressions.UnaryExpression)
            {
                varName = ((System.Linq.Expressions.MemberExpression)(((System.Linq.Expressions.UnaryExpression)exp.Body).Operand)).Member.Name;
            }
            else if (exp.Body is System.Linq.Expressions.MemberExpression)
            {
                varName = ((System.Linq.Expressions.MemberExpression)exp.Body).Member.Name;
            }
            else if (exp.Body is System.Linq.Expressions.ParameterExpression)
            {
                varName = ((System.Linq.Expressions.ParameterExpression)exp.Body).Type.Name;
            }

            return varName;
        }
        */

        ///// <summary>
        ///// 无序遍历集合
        ///// </summary>
        ///// <typeparam name="T">集合项类型</typeparam>
        ///// <param name="items">集合</param>
        ///// <param name="func">集合项要做的处理委托[返回值:true:继续遍历其它项;false:循环结束]</param>
        //public static void DisorderLoop<T>(IEnumerable<T> items, Func<T, bool> func)
        //{
        //    if (items == null)
        //    {
        //        throw new ArgumentNullException(nameof(items));
        //    }

        //    if (func == null)
        //    {
        //        throw new ArgumentNullException(nameof(func));
        //    }

        //    int count = items.Count();
        //    //空集合直接返回
        //    if (count == 0)
        //    {
        //        return;
        //    }

        //    int length = count / 2;
        //    if (count % 2 != 0)
        //    {
        //        length += 1;
        //    }

        //    /*************************************************
        //     *    fp              pl      pr              rp
        //     * |-->|              |<--|-->|              |<--|
        //     * |______________________|______________________|
        //     **************************************************/
        //    int fp = 0;
        //    int pl = length - 1;
        //    int pr = 0;
        //    int rp = count - 1;
        //    T tmpItem;

        //    //fp,pl,pr,rp为四个方向移动的索引指针
        //    for (fp = 0, pr = length; fp < length; fp++, pr++)
        //    {
        //        if (fp <= pl)
        //        {
        //            tmpItem = items.ElementAt(fp);
        //            if (!func(tmpItem))
        //            {
        //                break;
        //            }
        //        }

        //        if (pl > fp)
        //        {
        //            tmpItem = items.ElementAt(pl);
        //            if (!func(tmpItem))
        //            {
        //                break;
        //            }

        //            pl--;
        //        }

        //        if (pr <= rp)
        //        {
        //            tmpItem = items.ElementAt(pr);
        //            if (!func(tmpItem))
        //            {
        //                break;
        //            }
        //        }

        //        if (rp > pr)
        //        {
        //            tmpItem = items.ElementAt(rp);
        //            if (!func(tmpItem))
        //            {
        //                break;
        //            }

        //            rp--;
        //        }
        //    }
        //}

        /// <summary>
        /// 获取当前可用物理内存大小(Microsoft.VisualBasic程序集->Microsoft.VisualBasic.Devices.ComputerInfo.AvailablePhysicalMemory)
        /// </summary>
        /// <returns>当前可用物理内存大小</returns>
        public static ulong GetAvailablePhysicalMemory()
        {
            //var cm = new Microsoft.VisualBasic.Devices.ComputerInfo();
            //return cm.AvailablePhysicalMemory;
            throw new NotImplementedException();
        }

        /// <summary>
        /// 将指定对象快速ToSting出内容,只到obj对象的第一级,不支持树状结构
        /// </summary>
        /// <param name="obj">用于ToSting的对象</param>
        /// <param name="ignorePropertyNames">忽略的属性名称集合</param>
        /// <param name="newLine">是否每个属性独立一行[true:每个属性独立一行;false:所有属性连在一起不换行]</param>
        /// <param name="removeStrEOFChar">是否移除字符串中的结束字符（如果存在且不移除的话，结果中只显示结束符前的内容），[true:移除;false:保留]</param>
        /// <returns>Sting的对象</returns>
        public static string ToString(object obj, IEnumerable<string> ignorePropertyNames = null, bool newLine = false, bool removeStrEOFChar = true)
        {
            if (obj == null)
            {
                return "null";
            }

            Type type = obj.GetType();
            if (type.IsValueType)
            {
                return obj.ToString();
            }

            PropertyInfo[] propertyInfos = type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
            StringBuilder sb = new StringBuilder();
            object proValue;

            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                if (!propertyInfo.CanRead ||
                    ignorePropertyNames != null && ignorePropertyNames.Contains(propertyInfo.Name))
                {
                    //不可读或在忽略集合中,则忽略
                    continue;
                }

                if (sb.Length > 0)
                {
                    if (newLine)
                    {
                        sb.AppendLine(";");
                    }
                    else
                    {
                        sb.Append(';');
                    }
                }

                sb.Append(propertyInfo.Name);
                sb.Append(':');

                try
                {
                    proValue = propertyInfo.GetValue(obj, null);
                }
                catch (Exception)
                {
                    sb.Append("获取值异常");
                    continue;
                }

                if (proValue == null)
                {
                    sb.Append("null");
                }
                else
                {
                    if (propertyInfo.PropertyType.IsEnum)
                    {
                        sb.Append(proValue.ToString());
                    }
                    else if (propertyInfo.PropertyType == TypeEx.DateTimeType)
                    {
                        sb.Append(((DateTime)proValue).ToString("yyyy-MM-dd HH:mm:ss.fff"));
                    }
                    else if (propertyInfo.PropertyType == TypeEx.StringType)
                    {
                        if (removeStrEOFChar)
                        {
                            sb.Append(((string)proValue).Replace("\0", string.Empty));
                        }
                        else
                        {
                            sb.Append((string)proValue);
                        }
                    }
                    else
                    {
                        if (propertyInfo.PropertyType.IsPrimitive)
                        {
                            sb.Append(proValue);
                        }
                        else
                        {
                            sb.Append(JsonSerializer.SerializeObject(proValue));
                        }
                    }
                }
            }

            return sb.ToString();
        }


        #region EqualsEx
        private static int CompareTo(char left, IComparable right, TypeCode rightTypeCode)
        {
            switch (rightTypeCode)
            {
                case TypeCode.Char:
                    return left.CompareTo(right);
                case TypeCode.SByte:
                    return ((sbyte)left).CompareTo(right);
                case TypeCode.Byte:
                    return ((byte)left).CompareTo(right);
                case TypeCode.Int16:
                    return ((Int16)left).CompareTo(right);
                case TypeCode.UInt16:
                    return ((UInt16)left).CompareTo(right);
                case TypeCode.Int32:
                    return ((Int32)left).CompareTo(right);
                case TypeCode.UInt32:
                    return ((UInt32)left).CompareTo(right);
                case TypeCode.Int64:
                    return ((Int64)left).CompareTo(right);
                case TypeCode.UInt64:
                    return ((UInt64)left).CompareTo(right);
                case TypeCode.Single:
                    return ((float)left).CompareTo(right);
                case TypeCode.Double:
                    return ((double)left).CompareTo(right);
                case TypeCode.Decimal:
                    return ((decimal)left).CompareTo(right);
                case TypeCode.String:
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                default:
                    throw new NotSupportedException($"char不支持与{rightTypeCode.ToString()}类型比较");

            }
        }

        private static int CompareTo(sbyte left, IComparable right, TypeCode rightTypeCode)
        {
            switch (rightTypeCode)
            {
                case TypeCode.Char:
                    if (left < 0)
                    {
                        return -1;
                    }

                    return ((char)left).CompareTo(right);
                case TypeCode.SByte:
                    return left.CompareTo(right);
                case TypeCode.Byte:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var rightByteValue = (byte)right;
                    if (left > rightByteValue)
                    {
                        return 1;
                    }
                    else if (left == rightByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int16:
                    var int16ByteValue = (Int16)right;
                    if (left > int16ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int16ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt16:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var uint16ByteValue = (UInt16)right;
                    if (left > uint16ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint16ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int32:
                    var int32ByteValue = (Int32)right;
                    if (left > int32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt32:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var uint32ByteValue = (UInt32)right;
                    if (left > uint32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int64:
                    var int64ByteValue = (Int64)right;
                    if (left > int64ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt64:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var leftUInt64 = Convert.ToUInt64(right);
                    var uint64ByteValue = (UInt64)right;
                    if (leftUInt64 > uint64ByteValue)
                    {
                        return 1;
                    }
                    else if (leftUInt64 == uint64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Single:
                    var floatByteValue = (float)right;
                    if (left > floatByteValue)
                    {
                        return 1;
                    }
                    else if (left == floatByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Double:
                    var doubleByteValue = (double)right;
                    if (left > doubleByteValue)
                    {
                        return 1;
                    }
                    else if (left == doubleByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Decimal:
                    var decimalByteValue = (decimal)right;
                    if (left > decimalByteValue)
                    {
                        return 1;
                    }
                    else if (left == decimalByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.String:
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                default:
                    throw new NotSupportedException($"char不支持与{rightTypeCode.ToString()}类型比较");
            }
        }

        private static int CompareTo(byte left, IComparable right, TypeCode rightTypeCode)
        {
            switch (rightTypeCode)
            {
                case TypeCode.Char:
                    return ((char)left).CompareTo(right);
                case TypeCode.SByte:
                    var rightsByteValue = (sbyte)right;
                    if (left > rightsByteValue)
                    {
                        return 1;
                    }
                    else if (left == rightsByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Byte:
                    return left.CompareTo(right);
                case TypeCode.Int16:
                    var int16ByteValue = (Int16)right;
                    if (left > int16ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int16ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt16:
                    var uint16ByteValue = (UInt16)right;
                    if (left > uint16ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint16ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int32:
                    var int32ByteValue = (Int32)right;
                    if (left > int32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt32:
                    var uint32ByteValue = (UInt32)right;
                    if (left > uint32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int64:
                    var int64ByteValue = (Int64)right;
                    if (left > int64ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt64:
                    var uint64ByteValue = (UInt64)right;
                    if (left > uint64ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Single:
                    var floatByteValue = (float)right;
                    if (left > floatByteValue)
                    {
                        return 1;
                    }
                    else if (left == floatByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Double:
                    var doubleByteValue = (double)right;
                    if (left > doubleByteValue)
                    {
                        return 1;
                    }
                    else if (left == doubleByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Decimal:
                    var decimalByteValue = (decimal)right;
                    if (left > decimalByteValue)
                    {
                        return 1;
                    }
                    else if (left == decimalByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.String:
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                default:
                    throw new NotSupportedException($"char不支持与{rightTypeCode.ToString()}类型比较");
            }
        }

        private static int CompareTo(Int16 left, IComparable right, TypeCode rightTypeCode)
        {
            switch (rightTypeCode)
            {
                case TypeCode.Char:
                    if (left < 0)
                    {
                        return -1;
                    }
                    else
                    {
                        return ((char)left).CompareTo(right);
                    }
                case TypeCode.SByte:
                    var rightsByteValue = (sbyte)right;
                    if (left > rightsByteValue)
                    {
                        return 1;
                    }
                    else if (left == rightsByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Byte:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var byteValue = (byte)right;
                    if (left > byteValue)
                    {
                        return 1;
                    }
                    else if (left == byteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int16:
                    return left.CompareTo(right);
                case TypeCode.UInt16:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var uint16ByteValue = (UInt16)right;
                    if (left > uint16ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint16ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int32:
                    var int32ByteValue = (Int32)right;
                    if (left > int32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt32:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var uint32ByteValue = (UInt32)right;
                    if (left > uint32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int64:
                    var int64ByteValue = (Int64)right;
                    if (left > int64ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt64:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var leftUInt64 = Convert.ToUInt64(left);
                    var uint64ByteValue = (UInt64)right;
                    if (leftUInt64 > uint64ByteValue)
                    {
                        return 1;
                    }
                    else if (leftUInt64 == uint64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Single:
                    var floatByteValue = (float)right;
                    if (left > floatByteValue)
                    {
                        return 1;
                    }
                    else if (left == floatByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Double:
                    var doubleByteValue = (double)right;
                    if (left > doubleByteValue)
                    {
                        return 1;
                    }
                    else if (left == doubleByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Decimal:
                    var decimalByteValue = (decimal)right;
                    if (left > decimalByteValue)
                    {
                        return 1;
                    }
                    else if (left == decimalByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.String:
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                default:
                    throw new NotSupportedException($"char不支持与{rightTypeCode.ToString()}类型比较");
            }
        }

        private static int CompareTo(UInt16 left, IComparable right, TypeCode rightTypeCode)
        {
            switch (rightTypeCode)
            {
                case TypeCode.Char:
                    return ((char)left).CompareTo(right);
                case TypeCode.SByte:
                    var rightsByteValue = (sbyte)right;
                    if (left > rightsByteValue)
                    {
                        return 1;
                    }
                    else if (left == rightsByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Byte:
                    var byteValue = (byte)right;
                    if (left > byteValue)
                    {
                        return 1;
                    }
                    else if (left == byteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int16:
                    var int16ByteValue = (Int16)right;
                    if (left > int16ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int16ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt16:
                    return left.CompareTo(right);
                case TypeCode.Int32:
                    var int32ByteValue = (Int32)right;
                    if (left > int32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt32:
                    var uint32ByteValue = (UInt32)right;
                    if (left > uint32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int64:
                    var int64ByteValue = (Int64)right;
                    if (left > int64ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt64:
                    var uint64ByteValue = (UInt64)right;
                    if (left > uint64ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Single:
                    var floatByteValue = (float)right;
                    if (left > floatByteValue)
                    {
                        return 1;
                    }
                    else if (left == floatByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Double:
                    var doubleByteValue = (double)right;
                    if (left > doubleByteValue)
                    {
                        return 1;
                    }
                    else if (left == doubleByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Decimal:
                    var decimalByteValue = (decimal)right;
                    if (left > decimalByteValue)
                    {
                        return 1;
                    }
                    else if (left == decimalByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.String:
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                default:
                    throw new NotSupportedException($"char不支持与{rightTypeCode.ToString()}类型比较");
            }
        }

        private static int CompareTo(Int32 left, IComparable right, TypeCode rightTypeCode)
        {
            switch (rightTypeCode)
            {
                case TypeCode.Char:
                    if (left < 0)
                    {
                        return -1;
                    }
                    else
                    {
                        return ((char)left).CompareTo(right);
                    }
                case TypeCode.SByte:
                    var rightsByteValue = (sbyte)right;
                    if (left > rightsByteValue)
                    {
                        return 1;
                    }
                    else if (left == rightsByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Byte:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var byteValue = (byte)right;
                    if (left > byteValue)
                    {
                        return 1;
                    }
                    else if (left == byteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int16:
                    var int16Value = (Int16)right;
                    if (left > int16Value)
                    {
                        return 1;
                    }
                    else if (left == int16Value)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt16:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var uint16ByteValue = (UInt16)right;
                    if (left > uint16ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint16ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int32:
                    return left.CompareTo(right);
                case TypeCode.UInt32:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var uint32ByteValue = (UInt32)right;
                    if (left > uint32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int64:
                    var int64ByteValue = (Int64)right;
                    if (left > int64ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt64:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var leftUInt64 = Convert.ToUInt64(left);
                    var uint64ByteValue = (UInt64)right;
                    if (leftUInt64 > uint64ByteValue)
                    {
                        return 1;
                    }
                    else if (leftUInt64 == uint64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Single:
                    var floatByteValue = (float)right;
                    if (left > floatByteValue)
                    {
                        return 1;
                    }
                    else if (left == floatByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Double:
                    var doubleByteValue = (double)right;
                    if (left > doubleByteValue)
                    {
                        return 1;
                    }
                    else if (left == doubleByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Decimal:
                    var decimalByteValue = (decimal)right;
                    if (left > decimalByteValue)
                    {
                        return 1;
                    }
                    else if (left == decimalByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.String:
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                default:
                    throw new NotSupportedException($"char不支持与{rightTypeCode.ToString()}类型比较");
            }
        }

        private static int CompareTo(UInt32 left, IComparable right, TypeCode rightTypeCode)
        {
            switch (rightTypeCode)
            {
                case TypeCode.Char:
                    return ((char)left).CompareTo(right);
                case TypeCode.SByte:
                    var rightsByteValue = (sbyte)right;
                    if (left > rightsByteValue)
                    {
                        return 1;
                    }
                    else if (left == rightsByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Byte:
                    var byteValue = (byte)right;
                    if (left > byteValue)
                    {
                        return 1;
                    }
                    else if (left == byteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int16:
                    var int16ByteValue = (Int16)right;
                    if (left > int16ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int16ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt16:
                    var uint16ByteValue = (UInt16)right;
                    if (left > uint16ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint16ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int32:
                    var int32ByteValue = (Int32)right;
                    if (left > int32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt32:
                    return left.CompareTo(right);
                case TypeCode.Int64:
                    var int64ByteValue = (Int64)right;
                    if (left > int64ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt64:
                    var uint64ByteValue = (UInt64)right;
                    if (left > uint64ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Single:
                    var floatByteValue = (float)right;
                    if (left > floatByteValue)
                    {
                        return 1;
                    }
                    else if (left == floatByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Double:
                    var doubleByteValue = (double)right;
                    if (left > doubleByteValue)
                    {
                        return 1;
                    }
                    else if (left == doubleByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Decimal:
                    var decimalByteValue = (decimal)right;
                    if (left > decimalByteValue)
                    {
                        return 1;
                    }
                    else if (left == decimalByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.String:
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                default:
                    throw new NotSupportedException($"char不支持与{rightTypeCode.ToString()}类型比较");
            }
        }

        private static int CompareTo(Int64 left, IComparable right, TypeCode rightTypeCode)
        {
            switch (rightTypeCode)
            {
                case TypeCode.Char:
                    if (left < 0)
                    {
                        return -1;
                    }
                    else
                    {
                        return ((char)left).CompareTo(right);
                    }
                case TypeCode.SByte:
                    var rightsByteValue = (sbyte)right;
                    if (left > rightsByteValue)
                    {
                        return 1;
                    }
                    else if (left == rightsByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Byte:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var byteValue = (byte)right;
                    if (left > byteValue)
                    {
                        return 1;
                    }
                    else if (left == byteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int16:
                    var int16Value = (Int16)right;
                    if (left > int16Value)
                    {
                        return 1;
                    }
                    else if (left == int16Value)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt16:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var uint16ByteValue = (UInt16)right;
                    if (left > uint16ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint16ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int32:
                    var int32ByteValue = (Int32)right;
                    if (left > int32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == int32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt32:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var uint32ByteValue = (UInt32)right;
                    if (left > uint32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int64:
                    return left.CompareTo(right);
                case TypeCode.UInt64:
                    if (left < 0)
                    {
                        return -1;
                    }

                    var leftUInt64 = Convert.ToUInt64(left);
                    var uint64ByteValue = (UInt64)right;
                    if (leftUInt64 > uint64ByteValue)
                    {
                        return 1;
                    }
                    else if (leftUInt64 == uint64ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Single:
                    var floatByteValue = (float)right;
                    if (left > floatByteValue)
                    {
                        return 1;
                    }
                    else if (left == floatByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Double:
                    var doubleByteValue = (double)right;
                    if (left > doubleByteValue)
                    {
                        return 1;
                    }
                    else if (left == doubleByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Decimal:
                    var decimalByteValue = (decimal)right;
                    if (left > decimalByteValue)
                    {
                        return 1;
                    }
                    else if (left == decimalByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.String:
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                default:
                    throw new NotSupportedException($"char不支持与{rightTypeCode.ToString()}类型比较");
            }
        }

        private static int CompareTo(UInt64 left, IComparable right, TypeCode rightTypeCode)
        {
            switch (rightTypeCode)
            {
                case TypeCode.Char:
                    return ((char)left).CompareTo(right);
                case TypeCode.SByte:
                    var rightsSByteValue = (sbyte)right;
                    if (rightsSByteValue < 0)
                    {
                        return -1;
                    }

                    var rightsSByteValue2 = Convert.ToUInt64(right);
                    if (left > rightsSByteValue2)
                    {
                        return 1;
                    }
                    else if (left == rightsSByteValue2)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Byte:
                    var byteValue = (byte)right;
                    if (left > byteValue)
                    {
                        return 1;
                    }
                    else if (left == byteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int16:
                    var int16ByteValue = (Int16)right;
                    if (int16ByteValue < 0)
                    {
                        return -1;
                    }

                    var int16ByteValue2 = Convert.ToUInt64(right);
                    if (left > int16ByteValue2)
                    {
                        return 1;
                    }
                    else if (left == int16ByteValue2)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt16:
                    var uint16ByteValue = (UInt16)right;
                    if (left > uint16ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint16ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int32:
                    var int32ByteValue = (Int32)right;
                    if (int32ByteValue < 0)
                    {
                        return -1;
                    }

                    var int32ByteValue2 = Convert.ToUInt64(right);
                    if (left > int32ByteValue2)
                    {
                        return 1;
                    }
                    else if (left == int32ByteValue2)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt32:
                    var uint32ByteValue = (UInt32)right;
                    if (left > uint32ByteValue)
                    {
                        return 1;
                    }
                    else if (left == uint32ByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Int64:
                    var int64ByteValue = (Int64)right;
                    if (int64ByteValue < 0)
                    {
                        return -1;
                    }

                    var int64ByteValue2 = Convert.ToUInt64(right);
                    if (left > int64ByteValue2)
                    {
                        return 1;
                    }
                    else if (left == int64ByteValue2)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.UInt64:
                    return left.CompareTo(right);
                case TypeCode.Single:
                    var floatByteValue = (float)right;
                    if (left > floatByteValue)
                    {
                        return 1;
                    }
                    else if (left == floatByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Double:
                    var doubleByteValue = (double)right;
                    if (left > doubleByteValue)
                    {
                        return 1;
                    }
                    else if (left == doubleByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.Decimal:
                    var decimalByteValue = (decimal)right;
                    if (left > decimalByteValue)
                    {
                        return 1;
                    }
                    else if (left == decimalByteValue)
                    {
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                case TypeCode.String:
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                default:
                    throw new NotSupportedException($"char不支持与{rightTypeCode.ToString()}类型比较");
            }
        }

        private static int CompareTo(float left, IComparable right, TypeCode rightTypeCode)
        {
            switch (rightTypeCode)
            {
                case TypeCode.Char:
                    if (left < 0)
                    {
                        return -1;
                    }
                    else
                    {
                        return ((char)left).CompareTo(right);
                    }
                case TypeCode.SByte:
                    var rightsSByteValue = (sbyte)right;
                    if (left > rightsSByteValue)
                    {
                        return 1;
                    }
                    else if (left < rightsSByteValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Byte:
                    var byteValue = (byte)right;
                    if (left > byteValue)
                    {
                        return 1;
                    }
                    else if (left < byteValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Int16:
                    var int16Value = (Int16)right;
                    if (left > int16Value)
                    {
                        return 1;
                    }
                    else if (left < int16Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.UInt16:
                    var uint16Value = (UInt16)right;
                    if (left > uint16Value)
                    {
                        return 1;
                    }
                    else if (left < uint16Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Int32:
                    var int32Value = (Int32)right;
                    if (left > int32Value)
                    {
                        return 1;
                    }
                    else if (left < int32Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.UInt32:
                    var uint32Value = (UInt32)right;
                    if (left > uint32Value)
                    {
                        return 1;
                    }
                    else if (left < uint32Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Int64:
                    var int64Value = (Int64)right;
                    if (left > int64Value)
                    {
                        return 1;
                    }
                    else if (left < int64Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.UInt64:
                    var uint64Value = (UInt64)right;
                    if (left > uint64Value)
                    {
                        return 1;
                    }
                    else if (left < uint64Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Single:
                    var floatValue = (float)right;
                    if (left > floatValue)
                    {
                        return 1;
                    }
                    else if (left < floatValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Double:
                    var doubleValue = (double)right;
                    if (left > doubleValue)
                    {
                        return 1;
                    }
                    else if (left < doubleValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Decimal:
                    var leftDecimalValue = (decimal)left;
                    var decimalValue = (decimal)right;
                    if (leftDecimalValue > decimalValue)
                    {
                        return 1;
                    }
                    else if (leftDecimalValue < decimalValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.String:
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                default:
                    throw new NotSupportedException($"char不支持与{rightTypeCode.ToString()}类型比较");
            }
        }

        private static int CompareTo(double left, IComparable right, TypeCode rightTypeCode)
        {
            switch (rightTypeCode)
            {
                case TypeCode.Char:
                    if (left < 0)
                    {
                        return -1;
                    }
                    else
                    {
                        return ((char)left).CompareTo(right);
                    }
                case TypeCode.SByte:
                    var rightsSByteValue = (sbyte)right;
                    if (left > rightsSByteValue)
                    {
                        return 1;
                    }
                    else if (left < rightsSByteValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Byte:
                    var byteValue = (byte)right;
                    if (left > byteValue)
                    {
                        return 1;
                    }
                    else if (left < byteValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Int16:
                    var int16Value = (Int16)right;
                    if (left > int16Value)
                    {
                        return 1;
                    }
                    else if (left < int16Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.UInt16:
                    var uint16Value = (UInt16)right;
                    if (left > uint16Value)
                    {
                        return 1;
                    }
                    else if (left < uint16Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Int32:
                    var int32Value = (Int32)right;
                    if (left > int32Value)
                    {
                        return 1;
                    }
                    else if (left < int32Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.UInt32:
                    var uint32Value = (UInt32)right;
                    if (left > uint32Value)
                    {
                        return 1;
                    }
                    else if (left < uint32Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Int64:
                    var int64Value = (Int64)right;
                    if (left > int64Value)
                    {
                        return 1;
                    }
                    else if (left < int64Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.UInt64:
                    var uint64Value = (UInt64)right;
                    if (left > uint64Value)
                    {
                        return 1;
                    }
                    else if (left < uint64Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Single:
                    var floatValue = (float)right;
                    if (left > floatValue)
                    {
                        return 1;
                    }
                    else if (left < floatValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Double:
                    var doubleValue = (double)right;
                    if (left > doubleValue)
                    {
                        return 1;
                    }
                    else if (left < doubleValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Decimal:
                    var leftDecimalValue = (decimal)left;
                    var decimalValue = (decimal)right;
                    if (leftDecimalValue > decimalValue)
                    {
                        return 1;
                    }
                    else if (leftDecimalValue < decimalValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.String:
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                default:
                    throw new NotSupportedException($"char不支持与{rightTypeCode.ToString()}类型比较");
            }
        }

        /// <summary>
        /// 比较两对象是否相等[第一个对象大于第二个对象返回1,相等返回0;小于返回-1]
        /// </summary>
        /// <param name="left">第一个比较对象</param>
        /// <param name="right">第二个比较对象</param>
        /// <param name="rightTypeCode"></param>
        /// <returns>第一个对象大于第二个对象返回1,相等返回0;小于返回-1</returns>
        private static int CompareTo(decimal left, IComparable right, TypeCode rightTypeCode)
        {
            switch (rightTypeCode)
            {
                case TypeCode.Char:
                    if (left < 0)
                    {
                        return -1;
                    }
                    else
                    {
                        long left2 = (Int64)Math.Floor(left);

                        if (left - left2 > 0)
                        {
                            //有小数位,不等
                            return -1;
                        }
                        else
                        {
                            return ((char)left2).CompareTo(right);
                        }
                    }
                case TypeCode.SByte:
                    var rightsSByteValue = (sbyte)right;
                    if (left > rightsSByteValue)
                    {
                        return 1;
                    }
                    else if (left < rightsSByteValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Byte:
                    var byteValue = (byte)right;
                    if (left > byteValue)
                    {
                        return 1;
                    }
                    else if (left < byteValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Int16:
                    var int16Value = (Int16)right;
                    if (left > int16Value)
                    {
                        return 1;
                    }
                    else if (left < int16Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.UInt16:
                    var uint16Value = (UInt16)right;
                    if (left > uint16Value)
                    {
                        return 1;
                    }
                    else if (left < uint16Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Int32:
                    var int32Value = (Int32)right;
                    if (left > int32Value)
                    {
                        return 1;
                    }
                    else if (left < int32Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.UInt32:
                    var uint32Value = (UInt32)right;
                    if (left > uint32Value)
                    {
                        return 1;
                    }
                    else if (left < uint32Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Int64:
                    var int64Value = (Int64)right;
                    if (left > int64Value)
                    {
                        return 1;
                    }
                    else if (left < int64Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.UInt64:
                    var uint64Value = (UInt64)right;
                    if (left > uint64Value)
                    {
                        return 1;
                    }
                    else if (left < uint64Value)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Single:
                    var floatValue = (decimal)((float)right);
                    if (left > floatValue)
                    {
                        return 1;
                    }
                    else if (left < floatValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Double:
                    var doubleValue = (decimal)((double)right);
                    if (left > doubleValue)
                    {
                        return 1;
                    }
                    else if (left < doubleValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.Decimal:
                    var decimalValue = (decimal)right;
                    if (left > decimalValue)
                    {
                        return 1;
                    }
                    else if (left < decimalValue)
                    {
                        return -1;
                    }
                    else
                    {
                        return 0;
                    }
                case TypeCode.String:
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                default:
                    throw new NotSupportedException($"char不支持与{rightTypeCode.ToString()}类型比较");
            }
        }

        /// <summary>
        /// 比较两对象[left大于right返回1;left等于right返回0;left小于right返回-1],
        /// 如果类型不同,且都为引用类型,则默认left大于right,否则引用类型大于值类型;
        /// </summary>
        /// <param name="left">第一个比较对象</param>
        /// <param name="right">第二个比较对象</param>
        /// <returns>left大于right返回1;left等于right返回0;left小于right返回-1</returns>
        public static int CompareTo(IComparable left, IComparable right)
        {
            if (left == null)
            {
                if (right == null)
                {
                    return 0;
                }
                else
                {
                    return 1;
                }
            }

            if (right == null)
            {
                return -1;
            }

            Type leftType = left.GetType();
            Type rightType = right.GetType();

            if (leftType.IsClass)
            {
                if (rightType.IsClass)
                {
                    if (leftType == rightType)
                    {
                        //引用类型在此比较
                        return left.CompareTo(right);
                    }
                    else
                    {
                        return 1;
                    }
                }
                else
                {
                    return 1;
                }
            }

            if (rightType.IsClass)
            {
                return -1;
            }

            var leftTypeCode = Type.GetTypeCode(leftType);
            var rightTypeCode = Type.GetTypeCode(rightType);
            if (leftTypeCode == rightTypeCode)
            {
                return left.CompareTo(right);
            }

            int compareRet;
            switch (leftTypeCode)
            {
                case TypeCode.Char:
                    compareRet = CompareTo((char)left, right, rightTypeCode);
                    break;
                case TypeCode.SByte:
                    compareRet = CompareTo((sbyte)left, right, rightTypeCode);
                    break;
                case TypeCode.Byte:
                    compareRet = CompareTo((byte)left, right, rightTypeCode);
                    break;
                case TypeCode.Int16:
                    compareRet = CompareTo((Int16)left, right, rightTypeCode);
                    break;
                case TypeCode.UInt16:
                    compareRet = CompareTo((UInt16)left, right, rightTypeCode);
                    break;
                case TypeCode.Int32:
                    compareRet = CompareTo((Int32)left, right, rightTypeCode);
                    break;
                case TypeCode.UInt32:
                    compareRet = CompareTo((UInt32)left, right, rightTypeCode);
                    break;
                case TypeCode.Int64:
                    compareRet = CompareTo((Int64)left, right, rightTypeCode);
                    break;
                case TypeCode.UInt64:
                    compareRet = CompareTo((UInt64)left, right, rightTypeCode);
                    break;
                case TypeCode.Single:
                    compareRet = CompareTo((float)left, right, rightTypeCode);
                    break;
                case TypeCode.Double:
                    compareRet = CompareTo((double)left, right, rightTypeCode);
                    break;
                case TypeCode.Decimal:
                    compareRet = CompareTo((decimal)left, right, rightTypeCode);
                    break;
                case TypeCode.Boolean:
                case TypeCode.DateTime:
                case TypeCode.String:
                default:
                    throw new NotSupportedException($"不支持与{leftTypeCode.ToString()}类型比较");
            }
            return compareRet;
        }

        /// <summary>
        /// 比较两对象是否相等[相等返回true;不等返回false]
        /// </summary>
        /// <param name="objA">第一个比较对象</param>
        /// <param name="objB">第二个比较对象</param>
        /// <returns>相等返回true;不等返回false</returns>
        public static bool EqualsEx(object objA, object objB)
        {
            if (object.ReferenceEquals(objA, objB) || object.Equals(objA, objB))
            {
                return true;
            }

            if (objA == null)
            {
                if (objB == null)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                if (objB == null)
                {
                    return false;
                }
                else
                {
                    try
                    {
                        return CompareTo(objA as IComparable, objB as IComparable) == 0;
                    }
                    catch (NotSupportedException)
                    {
                        return false;
                    }

                }
            }

        }

        #endregion




        /// <summary>
        /// 获取到数据类型T的最大值和最小值
        /// </summary>
        /// <typeparam name="T">值类型T</typeparam>
        /// <param name="minValue">最小值</param>
        /// <param name="maxValue">最大值</param>
        /// <exception cref="NotSupportedException">不支持的数据类型</exception>
        public static void GetValueTypeMinMaxValue<T>(out T minValue, out T maxValue)
        {
            TypeCode code = Type.GetTypeCode(typeof(T));
            object min, max;
            switch (code)
            {
                case TypeCode.Char:
                    min = char.MinValue;
                    max = char.MaxValue;
                    break;
                case TypeCode.Byte:
                    min = byte.MinValue;
                    max = byte.MaxValue;
                    break;
                case TypeCode.SByte:
                    min = sbyte.MinValue;
                    max = sbyte.MaxValue;
                    break;
                case TypeCode.Int16:
                    min = Int16.MinValue;
                    max = Int16.MaxValue;
                    break;
                case TypeCode.UInt16:
                    min = UInt16.MinValue;
                    max = UInt16.MaxValue;
                    break;
                case TypeCode.Int32:
                    min = Int32.MinValue;
                    max = Int32.MaxValue;
                    break;
                case TypeCode.UInt32:
                    min = UInt32.MinValue;
                    max = UInt32.MaxValue;
                    break;
                case TypeCode.Int64:
                    min = Int64.MinValue;
                    max = Int64.MaxValue;
                    break;
                case TypeCode.UInt64:
                    min = UInt64.MinValue;
                    max = UInt64.MaxValue;
                    break;
                case TypeCode.Single:
                    min = float.MinValue;
                    max = float.MaxValue;
                    break;
                case TypeCode.Double:
                    min = double.MinValue;
                    max = double.MaxValue;
                    break;
                case TypeCode.Decimal:
                    min = decimal.MinValue;
                    max = decimal.MaxValue;
                    break;
                case TypeCode.DateTime:
                    min = DateTime.MinValue;
                    max = DateTime.MaxValue;
                    break;
                default:
                    Type type = typeof(T);
                    if (type == TypeEx.TimeSpanType)
                    {
                        min = TimeSpan.MinValue;
                        max = TimeSpan.MaxValue;
                    }
                    else if (type == TypeEx.DateTimeOffsetType)
                    {
                        min = DateTimeOffset.MinValue;
                        max = DateTimeOffset.MaxValue;
                    }
#if CORE
                    else if (type == TypeEx.HalfType)
                    {
                        min = Half.MinValue;
                        max = Half.MaxValue;
                    }
                    else if (type == TypeEx.TimeOnlyType)
                    {
                        min = TimeOnly.MinValue;
                        max = TimeOnly.MaxValue;
                    }
                    else if (type == TypeEx.DateOnlyType)
                    {
                        min = DateOnly.MinValue;
                        max = DateOnly.MaxValue;
                    }
#endif
#if CORE7_P
                    else if (type == TypeEx.Int128Type)
                    {
                        min = Int128.MinValue;
                        max = Int128.MaxValue;
                    }
                    else if (type == TypeEx.UInt128Type)
                    {
                        min = UInt128.MinValue;
                        max = UInt128.MaxValue;
                    }
#endif
                    //else if (type == TypeEx.BigIntegerType)
                    //{
                    //    min = BigInteger.MinValue;
                    //    max = BigInteger.MaxValue;
                    //}
                    else if (type == TypeEx.ComplexType)
                    {
                        min = new Complex(double.MinValue, double.MinValue);
                        max = new Complex(double.MaxValue, double.MaxValue);
                    }
                    else
                    {
                        throw new NotSupportedException($"不支持的数据类型\"{typeof(T).FullName}\"");
                    }
                    break;
            }

            minValue = (T)min;
            maxValue = (T)max;
        }


    }


    /// <summary>
    /// IDisposable扩展接口
    /// </summary>
    public interface IDisposableZ : IDisposable
    {
        /// <summary>
        /// 获取当前对象释放标识[true:已释放;false:未释放]
        /// </summary>
        bool Disposed { get; }
    }
}
